<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
       <title>createElement</title>
   </head>
   <body>
       <div>
           <input id="teste" name="teste" class="text" size="40" value="Conteúdo dentro do campo" onclick="alert('Clicou no teste!')"/>
<?php


/**
 * Em um primeiro momento nos vem a cabeça, resolver o problema da
forma mais simples, mais obvia: criar a funcao createInput,
 * com os parametros que precisamos e copiando o valor da variavel
para o campo, como segue no exemplo:
 *
 *
 */

/**
 * Cria um elemento input html
 *
 * @param string $id o id do campo
 * @param string $name o name/nome do campo
 * @param class $class a classe css
 * @param integer $size o tamanho
 * @param string $value o valor para o campo
 * @param string $onclick evento a adicionar quando clicarmos no botão
 * @return string o elemento gerado
 */
 function createInput($id, $name, $class, $size=40, $value, $onclick)
 {
    return "<input id='$id' name='$name' class='$class' size='$size' value='$value' onclick='$onclick'/>";
 }

echo createInput('teste2','test2', 'text', 40, 'valor', "alert(\"clickado!!\")");

 /**
 * Funciona, mas isto não é muito prático, pois se não quisermosadicionar o evento onclick, ele vai ser gerado igual
 * e como fazemos para adicionar outros eventos??
 * Por fim, é uma solução aparentemente muito prática mas que, uma simples analise joga por água abaixo.
 *
 * Então resolvemos criar a função createElement, que cria dinamicamente qualquer elemento html de qualquer espécie.
 *
 * Fazendo uma simples analise, descobriremos que elementos html tem um tipo, attributos (os mais variados) e tem,
 * em alguns casos elementos internos
 *
 * Criamos a seguinte função.
 */


/**
 * Função que cria qualquer elemento html dinamicamente
 *
 * @param string $type o tipo do elemento
 * @param array $attributes um array de atributos html
 * @param string $innerHTML no caso de ser um elemento composto o conteúdo interno, que pode ser outro conteúdo gerado pela mesma função
 * @return string o texto referente ao elemento html
 */
function createElement( $type='input', array $attributes = array(),
$innerHTML = NULL)
{
   //como a função ja garante que attributes é um array contagem para ter certeza que ele tem algum conteúdo dentro
   if ( count($attributes) > 0 );
   {
       //passa por cada elemento do array de attributos
       foreach ( $attributes as $line => $info )
       {
           //gera um atributo html usando o índice e o valor destaposição do array
           $stringAttributes .= " $line=\"$info\""; // .= é concatenação de String
       }
   }
   //caso não tenha conteúdo interno gera um elemento simples, o caso de um input
   if ( ! $innerHTML )
   {
       return "<$type{$stringAttributes}/>";
   }
   else
   {
       //se for um elemento composto (com innerHTML) cria o texto html de forma diferenciada
       return "<$type{$stringAttributes}>$innerHTML</$type>";
   }
}

/*
 * Cria o elemento html passando o tipo e um array de parametros.
 * Acaba tornando-se muito semelhante a criação padrão do html, só que traduzida ao php,
 * Dessa forma você pode usar todo o pode das ferramentas php para tratar estes dados.
 *
 * Em um momento inicial não ganhamos nenhuma praticidade um usar esta forma.
 * Poderiamos alegar que o trabalho final é o mesmo, e se considerarmos o fato
 * de ter o processamento do script ja não valeria a pena, mas vale e vamos mostrar o porque
 */
$teste2 = createElement('input', array('id'=>'teste3','class'=>'text', 'size'=>'30','value'=>'gerado por uma função php dinâmica','onclick'=>"alert('Clicou no teste2');" ) );

//echo $teste2;

/**
 * Facilmente criamos uma div e colocamos o conteúdo de #teste2 como seu conteúdo interno
 */
$div = createElement('div', array('id'=>'divExemplo'), $teste2);
echo $div;

/**
 * Agora em 3 linhas de código criaremos 100 div's com 100 input's dentro
 */
 for ($i=0; $i<=30 ; $i++)
 {
    $content .= createElement('div', array('id'=>'Div'.$i), createElement('input', array('id'=>'input'.$i,'value'=>$i ) ) );
 }

 echo $content;

/*
 * Neste momento seria legal criamos aquela nossa função createInput utilizando-se da nossa nova função createElement.
 *
 */

/**
 *
 * Cria um input utilizando-se da função createElement
 *
 * @param <type> $id   o id e o nome do elemento
 * @param <type> $value o valor do elemento
 * @param <type> $class a classe css
 * @param <type> $size  o tamanho do campo
 * @param <type> $attributes os atributos extras
 * @return <type> o input html
 */
function createInput2($id, $value, $class, $size, $attributes)
{
    $attributes['id']    = $id;
    $attributes['name']  = $id; //ele seta o name igual ao id, isto facilita nossa vida
    $attributes['value'] = $value;
    $attributes['size']  = $size;

    return createElement('input', $attributes);
}

    echo createInput2('createInput2','createInput2Value', 'text', 40 , array('onclick' =>"alert(\"clickado!!\")" ) );


/**
 * Agora nossa função createInput2 é mais dinamica, e não renderiza atributos não necessários.
 */

/**
 * Saindo um pouco do PHP, vejamos como o javascript se comporta na
criação de novos elementos.
 */

?>
           
<script type="text\javascript">
   var element   = document.createElement('input'); //criamos o elemento, usamos $element para se assemelhar ao php
   element.id    = 'elementoJS'; //setamos seus attributos
   element.name  = 'elementoJS';
   element.size  = 20;
   element.value = 'gerado por js';
   element.setAttribute('onclick',"alert('gerado por js');"); //no caso no js precisava setar os eventos por setAttributo não conseguimos ir direto

   document.body.appendChild(element); //isso adiciona o elemento ao elemento body do html
</script>

<?php

/*
 * Interessante não?? Ele considera um elemento html como um objeto,
então vamos fazer o mesmo em nossa função,
 * que não será mais uma função, mas sim um classe, que gerará nossos objetos.
 */


/**
 * Classe elemento html, representação de um objeto html/javascript no PHP
 */
class HtmlElement
{
   public $tagName; //guarda o type do elemento

   public function __construct( $tagName )
   {
       $this->tagName = $tagName; //seta o type no elemento
   }

   /**
    * Função que gera o html de um element html, chamada
automaticamente quando temos um echo
    *
    * @return string o html gerado
    */
   public function __toString()
   {
       //NOTE fgenerateMode vai ser muito útil caso queiramos usar geração de elementos em outro tipo de html
       GLOBAL $generateMode; //pega a variavel global

       $generateMode    = strtoupper($generateMode); //uppercase, tudo maisculo
       $attributes      = get_object_vars($this); //função que pega todos os attributes do objeto
       $innerHTML   = implode('',is_array($this->innerHTML) ? $this->innerHTML : array($this->innerHTML) ) ; //tranforma num array caso não seja e implode seus elementos tornando-os String
       $tagName  = $this->tagName;

       if ( !$generateMode || $generateMode == 'PHP')
       {

           //como a função ja garante que attributes é um array contagem para ter certeza que ele tem algum conteúdo dentro
           if ( count($attributes) > 0 );
           {
               //passa por cada elemento do array de attributos
               foreach ( $attributes as $line => $info )
               {
                   //aqui temos um detalhe interessante, não podemos renderizar as propriedades innerHTML direto,
                   //nem a propriedade type, elas são controladas de forma diferente, logo abaixo
                   if ( $line != 'tagName' && $line != 'innerHTML' )
                   {
                       //gera um atributo html usando o índice e o valor desta posição do array
                       $stringAttributes .= " $line=\"$info\""; // .= é concatenação de String
                   }
               }
           }

           //caso não tenha conteúdo interno gera um elemento simples, o caso de um input
           if ( ! $innerHTML )
           {
               return "<$tagName{$stringAttributes}/>";
           }
           else
           {
               //se for um elemento composto (com $innerHTML) cria o texto html de forma diferenciada
               return "<$tagName{$stringAttributes}>$innerHTML</$tagName>";
           }
       }

       else
       {
            $variableName = '$'.$this->id;
            $elementString = "$variableName  = document.createElement('{$tagName}'); \n"; // \n é linha nova

            if ( count($attributes) > 0 );
            {
               //passa por cada elemento do array de attributos
               foreach ( $attributes as $line => $info )
               {
                   //neste Caso o innerHTML vai no objeto mesmo
                   if ( $line != '$tagName' )
                   {
                       //verifica se é um evento e faz o setAttribute
                       if ( stripos( $line , 'on' ) !== FALSE ) //retorna a posição de on no nome do attributo
                       {
                            $elementString .= "$variableName.setAttribute(\"$line\",\"$info\");\n"; // .= é concatenação de String
                       }
                       else
                       {
                            //gera um atributo html usando o índice e o valor desta posição do array
                            $elementString .= "$variableName.$line=\"$info\";\n"; // .= é concatenação de String
                       }
                   }
               }
            }

            return $elementString;
       }

/*
$element      = $document.createElement('input'); //criamos o elemento, usamos $element para se assemelhar ao php
$element.id   = 'elementoJS'; //setamos seus attributos
$element.name = 'elementoJS';
$element.size = 20;
$element.value = 'gerado por js';
$element.setAttribute('onclick',"alert('gerado por js');"); //no caso no js precisava setar os eventos por setAttributo não conseguimos ir direto

document.body.appendChild($element); //isso adiciona o elemento ao elemento body do html*/
       
   }

    /**
    * Funcao que emula a setAttribute do javascript
    *
    * @param string $attribute o nome do atributo
    * @param string $value o valor para o devido atributo
    */
   function setAttribute($attribute, $value)
   {
       $this->$attribute = $value;
   }
}

// então criamos nosso elemento
$element        = new HtmlElement('input');
$element->id    = 'inputTeste2'; //setamos seus attributes
$element->name  = 'inputTeste2';
$element->value = 'gerado por classe';
$element->setAttribute('onclick', "alert('gerado por classe');" ); //função usada pra emular o código do js

echo $element; // note que estamos echoando um objeto, isso só é possível pois ele tem a função mágica __toString

/**
 * Repare como o código orientado a objeto fica mais elegante, você pode definir suas propriedades a cada linha
 * sem precisar passar tudo em um único e enorme array.
 *
 *
 * Se quisermos que nosso código se assemelhe ainda mais, criamos uma classe document, com a função create element,
 * como segue abaixo;
 *
 */

/**
 * Classe element usada para emula o código js
 */
class Document
{
    /**
     * Função que cria um elemento html de qualquer tipo
     *
     * @param string $type
     * @return HtmlElement
     */
    public function createElement($type)
    {
        return  new HtmlElement($type);
    }
}


//Nosso novo código ficaria assim
$document       = new Document; //isto será criado somente uma vez em toda a aplicação
$element        = $document->createElement('input');
$element->id    = 'inputTeste3'; //setamos seus attributes
$element->name  = 'inputTeste3';
$element->value = 'inputTeste3';
$element->setAttribute('onclick', "alert('inputTeste3');" ); //função usada pra emular o código do js

echo $element;

/***
 * Agora faremos uma comparação com um novo código js modificado com intenções de assemelhar o JS com o PHP
 */

?>

<script type="text/javascript">
$document     = document; //atalho para se assemelhar ao php
$element      = $document.createElement('input'); //criamos o elemento, usamos $element para se assemelhar ao php
$element.id   = 'elementoJS'; //setamos seus attributos
$element.name = 'elementoJS';
$element.size = 20;
$element.value = 'gerado por js';
$element.setAttribute('onclick',"alert('gerado por js');"); //no caso no js precisava setar os eventos por setAttributo não conseguimos ir direto

document.body.appendChild($element); //isso adiciona o elemento ao elemento body do html
</script>

<?php

/**
 * Desconsiderando o $document que ja esta criado no navegador, no javascrit,
 * e o document.body.apppendChild que não implementamos ainda 
 * a única diferença rela é o "->" que no js é ".".
 * 
 * Hoje não temos como mudar o "ponteiro" nem de uma nem de outra linguagem,
 * mas com um replace do código "." por '->' nosso código javascript vira código php e vice-versa.
 * 
 * Repare:
 * 
 */
 
 $js = '
$element      = $document.createElement("input");
$element.id   = "elementoMisto";
$element.name = "elementoMisto";
$element.size = 20;
$element.value = "elemento misto";
$element.setAttribute("onclick","alert(\'elemento misto\');");
';

$php = str_replace('.', '->', $js); //trocamos o . do js pelo -> do PHP

eval( $php ); //eval força rodar uma string como se fosse um código PHP

echo $element; //ainda funcionando em função do__toString

/**
 * Agora geramos o código Javascript através do PHP
 */

$document       = new Document; //isto será criado somente uma vez em toda a aplicação
$element        = $document->createElement('input');
$element->id    = 'geracaoDeJsPeloPHP'; //setamos seus attributes
$element->name  = 'geracaoDeJsPeloPHP';
$element->value = 'geracaoDeJsPeloPHP';
$element->setAttribute('onclick', "alert('geracaoDeJsPeloPHP');" ); //função usada pra emular o código do js

global $generateMode; //definimos que generate mode é global
$generateMode = 'JS'; //setamos ele como JS para ativar o gerador js

//concatenamos o código dentro de uma tag script do js, e concatenos o seu appendChild
echo '<script type="text/javascript">'.$element. 'document.body.appendChild($geracaoDeJsPeloPHP);</script>';

$generateMode = 'PHP';

/**
 * Agora vamos brincar um pouquinho mais.
 * Vamos colocar um elemento dentro do outro e começar a criar sistema de árvore que o html possui.
 *
 */

$document       = new Document; //isto será criado somente uma vez em toda a aplicação
$element        = $document->createElement('div');
$element->id    = 'divTest'; //setamos seus attributes
$element->setAttribute('onclick', "alert('div');" ); //função usada pra emular o código do js
$inputA = new HtmlElement('input');
$inputA->value    = 'magicoA';
$inputB = new HtmlElement('input');
$inputB->value    = 'magicoB';
$element->innerHTML = array($inputA, $inputB);

echo $element;

?>

       </div>
   </body>
</html>